package com.net.core.intercept;


import com.net.core.intercept.wrapper.RequestWrapper;
import com.net.core.intercept.wrapper.ResponseWrapper;
import com.net.core.utils.MyUtils;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.Date;
import java.util.Enumeration;

@Component
@Slf4j
public class ResponseFilter implements Filter {

    static String MDC_KEY = "MDC-KEY";
    static String MDC_TIME = "MDC-TIME";

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
        String url = ((HttpServletRequest) request).getRequestURL().toString();
        if (UrlList.noPringLog(url)) {
            filterChain.doFilter(request, response);
            return;
        }
//        response.setCharacterEncoding("UTF-8");
//        // 这里需要重写ResponseWrapper，因为原方法是没有获取返回值的功能
//        RequestWrapper wrapRequest = new RequestWrapper( (HttpServletRequest) request, requestBody);
        String requestBody = getRequestBody((HttpServletRequest) request);
//        String headerData = getHeader((HttpServletRequest) request);
        doBefore(requestBody, url);

        RequestWrapper wrapRequest = new RequestWrapper((HttpServletRequest) request, requestBody);
        ResponseWrapper wrapperResponse = new ResponseWrapper((HttpServletResponse) response);
        // 这里只拦截返回，直接让请求过去，如果在请求前有处理，可以在这里处理
        filterChain.doFilter(wrapRequest, wrapperResponse);
        byte[] content = wrapperResponse.getResponseData();//获取返回值
        // 判断是否有值
        if (content.length > 0) {
            // 这里是返回的内容
            String str = new String(content, "UTF-8");
            //把返回值输出到客户端
            content = str.getBytes("UTF-8");
            logParams(str, url);
        }
        ServletOutputStream out = response.getOutputStream();
        out.write(content);
        out.flush();
    }

    private String getHeader(HttpServletRequest request) {
        StringBuilder headerData = new StringBuilder();
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String key = headerNames.nextElement();
            headerData.append(key).append("=").append(request.getHeader(key)).append(" ");
        }
        return headerData.toString();
    }

    public void logParams(String ret, String url) {
        String s = MDC.get(MDC_TIME);
        String requestId = MDC.get(MDC_KEY);
        StringBuilder sb = new StringBuilder();
        float handleTime = (System.currentTimeMillis() - Long.parseLong(s)) / 1000F;
        sb.append("\n==========================出参======================");
        sb.append("\n \t时间:\t").append(new Date().toLocaleString());
        sb.append("\n \t请求id:\t").append(requestId);
        sb.append("\n \t数据:\t").append(ret);
        sb.append("\n=====================================================");
        log.info(sb.toString());
        MDC.remove(MDC_TIME);
        MDC.remove(MDC_KEY);
    }

    public void doBefore(String data, String url) {
        // 接收到请求，记录请求内容
        // 记录下请求内容
        String id = System.currentTimeMillis() + MyUtils.getRandomNum(3);
        String requestId = MyUtils.generateId().substring(6, id.length() - 1);
        MDC.put(MDC_KEY, requestId);
        MDC.put(MDC_TIME, System.currentTimeMillis() + "");
        if (data == null || data.length() == 0) return;
        StringBuilder sb = new StringBuilder();
        sb.append("\n==========================入参======================");
        sb.append("\n \t时间:\t").append(new Date().toLocaleString());
        sb.append("\n \turl:\t").append(url);
        sb.append("\n \t请求id:\t").append(requestId);
        sb.append("\n \t数据:\t");
        // 获取参数, 只取自定义的参数, 自带的HttpServletRequest, HttpServletResponse不管
        sb.append(data);
        sb.append("\n=====================================================");
        log.info(sb.toString());
    }

    private String getRequestBody(HttpServletRequest request) throws UnsupportedEncodingException {
        String method = request.getMethod();
        StringBuffer sb = new StringBuffer();
        if ("GET".equalsIgnoreCase(method)) {
            String requestBody = request.getQueryString();
            if (requestBody != null) {
                sb.append(URLDecoder.decode(requestBody, "utf-8"));
            }
        } else if ("POST".equalsIgnoreCase(method)) {
            try {
                BufferedReader reader = request.getReader();
                String line;
                while ((line = reader.readLine()) != null) {
                    sb.append(line);
                }
            } catch (IOException e) {
                log.info("请求体读取失败" + e.getMessage());
            }
        }
        return sb.toString();
    }

}